
Reflect.defineProperty(Array.prototype, 'lastElement', {
	get(this: Array<any>){
		return this.length>0 ? Reflect.get(this, this.length-1) : undefined;
	},
	set(this: Array<any>, value: any){
		Reflect.set(this, this.length>0 ? this.length-1 : 0, value);
	},
	enumerable: true,
	configurable: false,
});

Array.prototype.forWait = async function(this: Array<any>, call){
	for(let i = 0; i < this.length; i++){
		await call(this[i], i, this);
	}
};

((_global_)=>{
	if(!Reflect.has(_global_, 'mtec')){
		Reflect.set(_global_, 'mtec', {});
		Reflect.set(mtec, '__mtec__', 'Many technologies');
	}

	if(!mtec.array){
		Reflect.set(mtec, 'array', {});
	}
	Reflect.set(mtec.array, '__space_description__', 'This is a mtec subnamespace for array');
})(window ?? globalThis);

mtec.array.random = function(list){
	if(!Array.isArray(list)) return list;
	if(list.length==0) return undefined;
	if(list.length==1) return list[0];
	return list[Math.floor(Math.random() * list.length)];
}

//@ts-ignore
mtec.array.randomeElement = function(list, len, repetition){
	len = len ?? 1;
	if(repetition===false) len = Math.min(len, list.length);
	repetition = repetition ?? len>list.length;


	let index_list: number[] = [];
	while(index_list.length < len){
		let index = mtec.number.random(0, list.length-1);
		if(!repetition) while(index_list.includes(index)) index = mtec.number.random(0, list.length-1);
		index_list.push(index);
	}

	return index_list.map(index=>list[index]);
}

mtec.array.last = function(list, index){
	if(!Array.isArray(list)) return list;
	if(list.length==0) return undefined;

	if(index){
		index = Number(index);
		index = Math.floor(isNaN(index) ? 0 : index) + 1;
		index = Math.max(1, Math.min(list.length, index));
	}else index = 1;

	return list[list.length-index];
}

//@ts-ignore
mtec.array.clear = function(list){
	return (Array.isArray(list) && list.length>0) ? list.splice(0, list.length) : [];
}

mtec.array.remove = function(arr: any[], element: any, head?: boolean){
	let verify: (el: any, i: number, arr: any[])=>boolean;
	if(element instanceof Function) verify = element;
	else verify = (el: any, i: number, arr: any[])=>el==element;

	let [point, end, direction] = (head??true) ? [0, arr.length, 1] : [arr.length-1, -1, -1];

	while(point!=end){
		if(verify(arr[point], point, arr)) break;
		point += direction;
	}

	return point.inRange(0, arr.length-1) ? arr.splice(point, 1)[0] : undefined;
}

mtec.array.create = function(size, call){
	return new Array(size).fill(null, 0, size).map((_, i)=>call(i));
}